package com.deeper.customview.ui.c7.exercise.c07e01;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;

public class SwapLayout extends ViewGroup {

    private static final int SNAP_VELOCITY = 600;
    private Scroller scroller;
    private VelocityTracker velocityTracker;
    private float lastMotionX = 0;//上次触摸屏的x位置

    private static final int TOUCH_STATE_STOP = 0X001;
    private static final int TOUCH_STATE_FLING = 0X002;
    private int touchState = TOUCH_STATE_STOP;
    private int touchSlop = 0; //最小滑动距离

    private boolean spread = true;//展开还是缩回


    public SwapLayout(Context context) {
        super(context);
    }


    public SwapLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public SwapLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        scroller = new Scroller(context);
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);

        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }


    private int measureWidth(int widthMeasureSpec) {
        int width = 0;

        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);

        if (mode == MeasureSpec.AT_MOST) {
            throw new IllegalStateException("must not be AT_MOST");
        } else {
            int n = getChildCount();
            if (n != 2) {
                throw new IllegalStateException("must be two children");
            }
            for (int i = 0; i < n; i++) {
                View child = getChildAt(i);
                int childWidth = child.getMeasuredWidth();
                width += childWidth;
            }
        }
        return width;
    }


    private int measureHeight(int heightMeasureSpec) {
        int height = 0;

        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);

        if (mode == MeasureSpec.AT_MOST) {
            throw new IllegalStateException("must not be AT_MOST");
        } else {
            height = size;
        }
        return height;
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int n = getChildCount();
        View child = null;
        int left = 0;
        int top = 0;
        int right = 0;
        int bottom = 0;
        for (int i = 0; i < n; i++) {
            child = getChildAt(i);
            if (i == 0) { //第一个
                left = -child.getMeasuredWidth();
                top = 0;
                right = 0;
                bottom = b;
            } else {//第二个
                left = 0;
                top = 0;
                right = child.getMeasuredWidth();
                bottom = b;
            }
            child.layout(left, top, right, bottom);
        }
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        final int x = (int) ev.getX();
        final int y = (int) ev.getY();
        if (action == MotionEvent.ACTION_MOVE &&
                touchState == TOUCH_STATE_STOP) {
            return true;
        }

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                lastMotionX = x;
                touchState = scroller.isFinished() ? TOUCH_STATE_STOP :
                        TOUCH_STATE_FLING;
                break;
            case MotionEvent.ACTION_MOVE:
                //滑动距离过小不算滑动
                final int dx = (int) Math.abs(x - lastMotionX);
                if (dx > touchSlop) {
                    touchState = TOUCH_STATE_FLING;
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                touchState = TOUCH_STATE_STOP;
                break;
        }
        return touchState != TOUCH_STATE_STOP;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (velocityTracker == null) {
            velocityTracker = VelocityTracker.obtain();
        }
        velocityTracker.addMovement(event);
        super.onTouchEvent(event);

        int action = event.getAction();
        final int x = (int) event.getX();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                //手指按下时，如果正在滚动
                if (scroller != null && !scroller.isFinished()) {
                    scroller.abortAnimation();
                }
                lastMotionX = x;
                break;
            case MotionEvent.ACTION_MOVE:
                //随手指滚动
                int dx = (int) (lastMotionX - x);

                if (dx < 0) {   //向右移
                    if (Math.abs(getScrollX()) + Math.abs(dx) >= Math.abs(getChildAt(0).getLeft())) {
                        //会超出左边
                        dx = getChildAt(0).getLeft() - getScrollX();
                    }
                } else if (dx > 0) {   //向左移
                    if (Math.abs(getScrollX()) - Math.abs(dx) <= Math.abs(getChildAt(0).getRight())) {
                        //会超出右边
                        dx = getChildAt(0).getRight() - getScrollX();
                    }
                }

                //滑动距离过小不算滑动
                if (Math.abs(dx) < 5) {
                    return false;
                }
                scrollBy(dx, 0);
                lastMotionX = x;
                break;
            case MotionEvent.ACTION_UP:
                final VelocityTracker velocityTracker = this.velocityTracker;
                velocityTracker.computeCurrentVelocity(1000);
                int velocityX = (int) velocityTracker.getXVelocity();

                //通过 velocityX 的正负值可以判断滑动方向
                if (velocityX > SNAP_VELOCITY) {
                    //右-展开
                    move(true);
                } else if (velocityX < -SNAP_VELOCITY) {
                    //左-缩回
                    move(false);
                } else {
                    move(Math.abs(getScrollX()) >= Math.abs(getChildAt(0).getLeft()) / 2);
                }
                break;
        }
        return true;
    }


    /**
     * 显示或隐藏侧边栏
     */
    public void spread() {
        if (getScrollX() == getChildAt(0).getRight()) {
            spread = true;
        }
        if (getScrollX() == getChildAt(0).getLeft()) {
            spread = false;
        }

        move(spread);
    }


    private void move(boolean spread) {
        int px = 0;
        int py = 0;
        if (spread) {
            px = getChildAt(0).getLeft() - getScrollX();
        } else {
            px = getChildAt(0).getRight() - getScrollX();
        }
        scroller.startScroll(getScrollX(), 0, px, py, 1500);
        invalidate();
    }


    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            //设置容器内组件新位置
            this.scrollTo(scroller.getCurrX(), scroller.getCurrY());
            //重绘以刷新产生动画
            postInvalidate();
        }
    }
}
